import matplotlib.pyplot as plt
import matplotlib.patches as patches

# 设置支持中文的字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题

# 创建画布和子图
fig, ax = plt.subplots(figsize=(12, 10))

# 隐藏坐标轴
ax.axis('off')

# 定义节点样式
node_style = dict(boxstyle="round,pad=0.3", fc="lightblue", ec="black", lw=2)
decision_style = dict(boxstyle="round,pad=0.3", fc="lightgreen", ec="black", lw=2)  # 决策节点样式
start_end_style = dict(boxstyle="round,pad=0.3", fc="orange", ec="black", lw=2)  # 开始/结束节点样式

# 定义箭头样式
arrow_style = dict(arrowstyle="->", color="black", lw=2)

# 定义节点位置
node_positions = {
    "start": (0.5, 0.95),
    "input": (0.5, 0.85),
    "tokenize": (0.5, 0.75),
    "parse": (0.5, 0.6),
    "evaluate": (0.5, 0.45),
    "output": (0.5, 0.35),
    "end": (0.5, 0.25),
    "tokenize_step1": (0.3, 0.7),
    "tokenize_step2": (0.3, 0.65),
    "tokenize_step3": (0.3, 0.6),
    "tokenize_step4": (0.3, 0.55),
    "tokenize_step5": (0.3, 0.5),
    "tokenize_step6": (0.3, 0.45),
    "parse_step1": (0.7, 0.7),
    "parse_step2": (0.7, 0.65),
    "parse_step3": (0.7, 0.6),
    "parse_step4": (0.7, 0.55),
    "parse_step5": (0.7, 0.5),
    "parse_step6": (0.7, 0.45),
    "evaluate_step1": (0.5, 0.4),
    "evaluate_step2": (0.5, 0.35),
    "evaluate_step3": (0.5, 0.3),
    "evaluate_step4": (0.5, 0.25),
}

# 绘制节点
start_node = ax.text(*node_positions["start"], "开始", ha="center", va="center", bbox=start_end_style)
input_node = ax.text(*node_positions["input"], "输入表达式", ha="center", va="center", bbox=node_style)
tokenize_node = ax.text(*node_positions["tokenize"], "词法分析", ha="center", va="center", bbox=node_style)
parse_node = ax.text(*node_positions["parse"], "语法分析", ha="center", va="center", bbox=node_style)
evaluate_node = ax.text(*node_positions["evaluate"], "表达式求值", ha="center", va="center", bbox=node_style)
output_node = ax.text(*node_positions["output"], "输出结果", ha="center", va="center", bbox=node_style)
end_node = ax.text(*node_positions["end"], "结束", ha="center", va="center", bbox=start_end_style)

# 词法分析详细步骤
tokenize_step1 = ax.text(*node_positions["tokenize_step1"], "逐个字符扫描", ha="center", va="center", bbox=node_style)
tokenize_step2 = ax.text(*node_positions["tokenize_step2"], "处理空格", ha="center", va="center", bbox=node_style)
tokenize_step3 = ax.text(*node_positions["tokenize_step3"], "处理运算符/括号", ha="center", va="center", bbox=node_style)
tokenize_step4 = ax.text(*node_positions["tokenize_step4"], "处理数字", ha="center", va="center", bbox=node_style)
tokenize_step5 = ax.text(*node_positions["tokenize_step5"], "处理一元运算符", ha="center", va="center", bbox=node_style)
tokenize_step6 = ax.text(*node_positions["tokenize_step6"], "添加结束符 #", ha="center", va="center", bbox=node_style)

# 语法分析详细步骤
parse_step1 = ax.text(*node_positions["parse_step1"], "初始化栈", ha="center", va="center", bbox=node_style)
parse_step2 = ax.text(*node_positions["parse_step2"], "处理词法单元", ha="center", va="center", bbox=node_style)
parse_step3 = ax.text(*node_positions["parse_step3"], "匹配终结符", ha="center", va="center", bbox=decision_style)
parse_step4 = ax.text(*node_positions["parse_step4"], "查找预测分析表", ha="center", va="center", bbox=node_style)
parse_step5 = ax.text(*node_positions["parse_step5"], "处理 ε", ha="center", va="center", bbox=node_style)
parse_step6 = ax.text(*node_positions["parse_step6"], "检查结束条件", ha="center", va="center", bbox=decision_style)

# 表达式求值详细步骤
evaluate_step1 = ax.text(*node_positions["evaluate_step1"], "调用 evaluate_E", ha="center", va="center", bbox=node_style)
evaluate_step2 = ax.text(*node_positions["evaluate_step2"], "调用 evaluate_T", ha="center", va="center", bbox=node_style)
evaluate_step3 = ax.text(*node_positions["evaluate_step3"], "调用 evaluate_F", ha="center", va="center", bbox=node_style)
evaluate_step4 = ax.text(*node_positions["evaluate_step4"], "处理数字/括号/一元运算符", ha="center", va="center", bbox=node_style)

# 绘制箭头
def draw_arrow(ax, start_pos, end_pos, arrow_style):
    ax.annotate("", xy=end_pos, xytext=start_pos, arrowprops=arrow_style)

# 主流程箭头
draw_arrow(ax, node_positions["start"], node_positions["input"], arrow_style)
draw_arrow(ax, node_positions["input"], node_positions["tokenize"], arrow_style)
draw_arrow(ax, node_positions["tokenize"], node_positions["parse"], arrow_style)
draw_arrow(ax, node_positions["parse"], node_positions["evaluate"], arrow_style)
draw_arrow(ax, node_positions["evaluate"], node_positions["output"], arrow_style)
draw_arrow(ax, node_positions["output"], node_positions["end"], arrow_style)

# 词法分析详细箭头
draw_arrow(ax, node_positions["tokenize"], node_positions["tokenize_step1"], arrow_style)
draw_arrow(ax, node_positions["tokenize_step1"], node_positions["tokenize_step2"], arrow_style)
draw_arrow(ax, node_positions["tokenize_step2"], node_positions["tokenize_step3"], arrow_style)
draw_arrow(ax, node_positions["tokenize_step3"], node_positions["tokenize_step4"], arrow_style)
draw_arrow(ax, node_positions["tokenize_step4"], node_positions["tokenize_step5"], arrow_style)
draw_arrow(ax, node_positions["tokenize_step5"], node_positions["tokenize_step6"], arrow_style)

# 语法分析详细箭头
draw_arrow(ax, node_positions["parse"], node_positions["parse_step1"], arrow_style)
draw_arrow(ax, node_positions["parse_step1"], node_positions["parse_step2"], arrow_style)
draw_arrow(ax, node_positions["parse_step2"], node_positions["parse_step3"], arrow_style)
draw_arrow(ax, node_positions["parse_step3"], node_positions["parse_step4"], arrow_style)
draw_arrow(ax, node_positions["parse_step4"], node_positions["parse_step5"], arrow_style)
draw_arrow(ax, node_positions["parse_step5"], node_positions["parse_step6"], arrow_style)

# 表达式求值详细箭头
draw_arrow(ax, node_positions["evaluate"], node_positions["evaluate_step1"], arrow_style)
draw_arrow(ax, node_positions["evaluate_step1"], node_positions["evaluate_step2"], arrow_style)
draw_arrow(ax, node_positions["evaluate_step2"], node_positions["evaluate_step3"], arrow_style)
draw_arrow(ax, node_positions["evaluate_step3"], node_positions["evaluate_step4"], arrow_style)

# 保存图像
plt.savefig('detailed_algorithm_flowchart.png', dpi=300, bbox_inches='tight')

# 显示图像
plt.show()